/*
     使用冒泡排序模拟实现qsort函数

     夏思成

     2024年3月17日
*/

#include <stdio.h>
#include <string.h>


struct student
{
    char name[32];
    int age;
};


//比较整型函数
int compare_by_int(const void* p1, const void* p2)
{
    return *((int*)p1) - *((int*)p2);
}


//比较字符串函数
int compare_by_struct_string(const void* p1, const void* p2)
{
    return strcmp(((struct student*)p1)->name, ((struct student*)p2)->name);
}


//比较结构体中的整型数据
int compare_by_struct_int(const void* p1, const void* p2)
{
    return ((struct student*)p1)->age - ((struct student*)p2)->age;
}


//交换函数
void swap(char* buf1, char* buf2,size_t width)
{
    int i = 0;
    for (i = 0; i < width; i++)
    {
        char tmp = *buf1;
        *buf1 = *buf2;
        *buf2 = tmp;
        buf1++;
        buf2++;
    }
}


//冒泡排序函数
//该函数模拟qsort函数，参数分别代表：
//待排序的数组或者结构体，待排序的数组或结构体大小，待排序中每一个元素的大小，比较函数用于判断是否需要交换
void bubble_sort(void* p, size_t sz, size_t width, int(*compare)(const void*,const void*))
{
    int i = 0;
    //趟数
    for (i = 0; i < sz - 1; i++)
    {
        //每趟比较次数
        int j = 0;
        for (j = 0; j < sz - 1 - i; j++)
        {
            //比较nums[j] 和 nums[j+1],判断是否需要交换
            if (compare((char*)p + width * j, (char*)p + width * (j + 1)) > 0)
            {
                //交换函数
                swap((char*)p + width * j, (char*)p + width * (j + 1), width);
            }
        }
    }
}


//打印整形数据函数
void print1(int* p, size_t sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", *(p + i));
    }
    printf("\n");
}


//打印结构体类型函数
void print2(struct student* p, size_t sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%s,%d\n", p->name, p->age);
        p++;
    }
}


//排序整型数组
void test1()
{
    int nums[] = { 10,9,8,7,6,5,4,3,2,1 };
    int sz = sizeof(nums) / sizeof(nums[0]);
    bubble_sort(nums, sz, sizeof(nums[0]), compare_by_int);
    print1(nums, sz);
}


//排序结构体,以字符串排序
void test2()
{
    struct student stu[3] = { {"zhangsan",8},{"lisi",18},{"wangwu",28} };
    int sz = sizeof(stu) / sizeof(stu[0]);
    bubble_sort(stu, sz, sizeof(stu[0]), compare_by_struct_string);
    print2(stu, sz);
}


//排序结构体，以整型数据排序
void test3()
{
    struct student stu[3] = { {"zhangsan",8},{"lisi",18},{"wangwu",28} };
    int sz = sizeof(stu) / sizeof(stu[0]);
    bubble_sort(stu, sz, sizeof(stu[0]), compare_by_struct_int);
    print2(stu, sz);
}


int main()
{
    //排序整型数组
    test1();

    //排序结构体,以姓名排序
    test2();

    //排序结构体，以年龄排序
    test3();
    return 0;
}